package com.niiwoo.civet.mobile.controller.invest;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.request.StatisticUserBillAmountRequestDTO;
import com.niiwoo.civet.account.dto.response.StatisticUserBillAmountReponseDTO;
import com.niiwoo.civet.account.enums.BillAmountStatisticsEnum;
import com.niiwoo.civet.account.service.bill.UserBillStatisticsDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.mobile.vo.request.invest.*;
import com.niiwoo.civet.mobile.vo.request.myloan.ProjectBorrowDetailRequestVO;
import com.niiwoo.civet.mobile.vo.response.invest.*;
import com.niiwoo.civet.trade.dto.request.InvestAmountStatisticsRequestDTO;
import com.niiwoo.civet.trade.dto.request.InvestOrderListRequestDTO;
import com.niiwoo.civet.trade.dto.request.InvestOrderStatusRequestDTO;
import com.niiwoo.civet.trade.dto.request.ProjectBorrowerPlanRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceProtocolloRequestDTO;
import com.niiwoo.civet.trade.dto.request.invest.InvestCalendarRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.MyProjectRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.MyloanRequestDTO;
import com.niiwoo.civet.trade.dto.response.*;
import com.niiwoo.civet.trade.dto.response.creditor.CreditorConfigDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestSwitchResponseDTO;
import com.niiwoo.civet.trade.dto.response.invest.DayInvestInfoResponseDTO;
import com.niiwoo.civet.trade.dto.response.myloan.UserProjectStatisticResponseDTO;
import com.niiwoo.civet.trade.dto.response.myloan.inner.BackToArticleDetails;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.service.configure.TradeConfigDubboService;
import com.niiwoo.civet.trade.service.creditor.CreditorConfigDubboService;
import com.niiwoo.civet.trade.service.intelligenceInvest.IntelligenceInvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestCalendarDubboService;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestOrderDubboService;
import com.niiwoo.civet.trade.service.invest.ReceivePaymentPlanDubboService;
import com.niiwoo.civet.trade.service.myloan.MyLoanDubboService;
import com.niiwoo.civet.user.dto.response.UserIdentityInfoResponseDTO;
import com.niiwoo.civet.user.service.UserIdentityDubboService;
import com.niiwoo.tripod.base.utils.DateUtils;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.vo.PageResponseVO;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;

/**
 * Created by lujing on 2018/5/12.
 */
@RestController
@RequestMapping("/investOrder")
@Api(tags = "易简-投资订单", description = "/investOrder")
@Slf4j
public class UserInvestOrderController {

    private static final Logger logger = LoggerFactory.getLogger(UserInvestOrderController.class);

    @Reference(version = "1.0.0")
    private InvestDubboService investDubboService;
    @Reference(version = "1.0.0")
    private ReceivePaymentPlanDubboService receivePaymentPlanDubboService;
    @Reference(version = "1.0.0")
    private InvestOrderDubboService investOrderDubboService;
    @Reference(version = "1.0.0")
    private TradeConfigDubboService tradeConfigDubboService;
    @Reference(version = "1.0.0")
    private UserIdentityDubboService userIdentityDubboService;
    @Reference(version = "1.0.0")
    private MyLoanDubboService myLoanDubboService;
    @Reference(version = "1.0.0")
    private CreditorConfigDubboService creditorConfigDubboService;
    @Reference(version = "1.0.0")
    private IntelligenceInvestDubboService intelligenceInvestDubboService;
    @Reference(version = "1.0.0")
    private InvestCalendarDubboService investCalendarDubboService;
    //极速借个人
    @Value("${h5-fastloan-contract-url}")
    private String h5FastloanContractUrl;
    //土巴兔
    @Value("${h5-orgloan-contract-url}")
    private String h5orgloanContractUrl;
    //鸿特个人
    @Value("${h5-OrgPersonalFastLoan-contract-url}")
    private String h5OrgPersonalFastLoanContract;
    //鸿特机构
    @Value("${h5-OrgCompanyFastLoan-contract-url}")
    private String h5OrgCompanyFastLoanContract;
    //俊拓个人
    @Value("${h5-JunTuoPersonalFastLoan-contract-url}")
    private String h5JunTuoPersonalFastLoanContract;
    //俊拓机构
    @Value("${h5-JunTuoCompanyFastLoan-contract-url}")
    private String h5JunTuoCompanyFastLoanContract;

    @Reference(version = "1.0.0")
    private UserBillStatisticsDubboService userBillStatisticsDubboService;


    /**
     * 风险提示书
     */
    @Value("${h5-invest-risk-tips-url}")
    private String h5InvestRiskTipsUrl;

    @PostMapping("/list")
    @ApiOperation("投资不同状态订单列表-易简")
    public Result<InvestOrderStatusListResponseVO> orderList(@RequestBody @Valid InvestStatusRequestVO investStatusRequestVO) {
        logger.info("orderList investStatusRequestVO:{}", JSON.toJSON(investStatusRequestVO));
        InvestOrderStatusRequestDTO requestDTO = new InvestOrderStatusRequestDTO();
        // 返回给前端的VO
        InvestOrderStatusListResponseVO listResponseVO = new InvestOrderStatusListResponseVO();
        PageResponseVO<InvestOrderStatusVO> pageResponseVO = new PageResponseVO<>();
        List<InvestOrderStatusVO> recordVOS = new ArrayList<>();
        // 封装处理业务的dto
        String userId = PrincipalContext.getUserId();
        requestDTO.setUserId(userId);
        requestDTO.setPageNumber(investStatusRequestVO.getPageNumber());
        requestDTO.setPageSize(investStatusRequestVO.getPageSize());
        requestDTO.setType(investStatusRequestVO.getType() == null ? 0 : investStatusRequestVO.getType());
        requestDTO.setStatus(investStatusRequestVO.getStatus());
        requestDTO.setProductType(investStatusRequestVO.getProductType());
        requestDTO.setQueryType(investStatusRequestVO.getQueryType());
        if (investStatusRequestVO.getStartTime() != null && investStatusRequestVO.getStartTime().getTime() != 0L) {
            requestDTO.setStartTime(investStatusRequestVO.getStartTime());
        }
        if (investStatusRequestVO.getEndTime() != null && investStatusRequestVO.getEndTime().getTime() != 0L) {
            requestDTO.setEndTime(investStatusRequestVO.getEndTime());
        }

        PageResponseDTO<InvestOrderStatusResponseDTO> investOrderPage = investOrderDubboService.queryInvestOrderList(requestDTO);

        if (investOrderPage.getTotalCount() > 0) {
            for (InvestOrderStatusResponseDTO investOrderStatusResponseDTO : investOrderPage.getItems()) {
                InvestOrderStatusVO investOrderStatusVO = new InvestOrderStatusVO();
                investOrderStatusVO.setHeadImg(investOrderStatusResponseDTO.getHeadImg());
                investOrderStatusVO.setNickName(investOrderStatusResponseDTO.getNickName());
                investOrderStatusVO.setDeadline(investOrderStatusResponseDTO.getDeadline());
                investOrderStatusVO.setDeadlineUnit(investOrderStatusResponseDTO.getDeadlineUnit());
                investOrderStatusVO.setBorrowRate(investOrderStatusResponseDTO.getBorrowRate());
                investOrderStatusVO.setAddRate(investOrderStatusResponseDTO.getAddRate());
                investOrderStatusVO.setAmount(investOrderStatusResponseDTO.getAmount());
                investOrderStatusVO.setInterest(investOrderStatusResponseDTO.getInterest());
                investOrderStatusVO.setTime(investOrderStatusResponseDTO.getTime());
                investOrderStatusVO.setOrderId(investOrderStatusResponseDTO.getOrderId());
                investOrderStatusVO.setStatus(investOrderStatusResponseDTO.getStatus());
                investOrderStatusVO.setProductType(investOrderStatusResponseDTO.getProductType());
                investOrderStatusVO.setProductTypeDesc(investOrderStatusResponseDTO.getProductTypeDesc());
                investOrderStatusVO.setOverdueMsg(investOrderStatusResponseDTO.getOverdueMsg());
                investOrderStatusVO.setIsCanInvest(investOrderStatusResponseDTO.getIsCanInvest());
                investOrderStatusVO.setProjectId(investOrderStatusResponseDTO.getProjectId());
                investOrderStatusVO.setRepayInterest(investOrderStatusResponseDTO.getRepayInterest());
                investOrderStatusVO.setRemainingDeadlineMonth(investOrderStatusResponseDTO.getRemainingDeadlineMonth());
                investOrderStatusVO.setRemainingDeadlineDay(investOrderStatusResponseDTO.getRemainingDeadlineDay());
                investOrderStatusVO.setIsEnterpriseProject(investOrderStatusResponseDTO.getIsEnterpriseProject());
                investOrderStatusVO.setIsShowOtherLoanTypeLabel(investOrderStatusResponseDTO.getIsShowOtherLoanTypeLabel());
                recordVOS.add(investOrderStatusVO);
            }
            pageResponseVO.setItems(recordVOS);

            listResponseVO.setOrdersNum(investOrderPage.getTotalCount());
        } else {
            listResponseVO.setMaxInterestRate(investOrderDubboService.getMaxRate());
        }
        InvestOrderMaxandMinDateResponseDTO dateResponseDTO = investOrderDubboService.getMyInvestOrderMaxandMinDate(userId, requestDTO.getType(), requestDTO.getQueryType());
        if (dateResponseDTO != null && dateResponseDTO.getMaxTime() != null) {
            listResponseVO.setMaxDate(dateResponseDTO.getMaxTime());
        }
        if (dateResponseDTO != null && dateResponseDTO.getMinTime() != null) {
            listResponseVO.setMinDate(dateResponseDTO.getMinTime());
        }
        // 检查用户是否有信用借或机构标的投资记录
        UserHasInvestResponseDTO userHasInvestResponseDTO = investOrderDubboService.checkUserHasInvest(userId);
        listResponseVO.setHasOrgInvest(userHasInvestResponseDTO.isHasOrgInvest());
        listResponseVO.setHasCreditLoanInvest(userHasInvestResponseDTO.isHasCreditLoanInvest());

        pageResponseVO.setTotalCount(investOrderPage.getTotalCount());
        pageResponseVO.setTotalPage(investOrderPage.getTotalPage());

        listResponseVO.setPageResponseVO(pageResponseVO);
        logger.info("orderList listResponseVO:{}", JSON.toJSON(listResponseVO));
        return Result.with(listResponseVO);
    }

    @PostMapping("/statistics")
    @ApiOperation("投资列表数据统计-易简")
    public Result<InvestStatisticsDataResponseVO> statisticsData() {
        String userId = PrincipalContext.getUserId();
        InvestStatisticsDataResponseVO dataVo = new InvestStatisticsDataResponseVO();
        InvestOrderStatisticsResponseDTO dataDto = investOrderDubboService.queryInvestOrderStatistcs(userId);
        if (dataDto != null) {
            dataVo.setEarnedIncome(dataDto.getEarnedIncome());
            dataVo.setRepayPriInter(dataDto.getRepayPriInter());
            dataVo.setTodayReturnMoney(dataDto.getTodayReturnMoney());
            dataVo.setRecentlyReturnMoney(dataDto.getRecentlyReturnMoney());
            dataVo.setRecentlyDate(dataDto.getRecentlyDate());
            dataVo.setRecentlyCapital(dataDto.getRecentlyCapital());
            dataVo.setRecentlyInterest(dataDto.getRecentlyInterest());
            dataVo.setRecentlyAddInterest(dataDto.getRecentlyAddInterest());
            dataVo.setReceivedInterest(dataDto.getReceivedInterest());
            dataVo.setReceivedPenaltyFee(dataDto.getReceivedPenaltyFee());
            dataVo.setReceivedAddInterest(dataDto.getReceivedAddInterest());
            dataVo.setInvestGiven(dataDto.getInvestGiven());
        }
        return Result.with(dataVo);
    }

    @PostMapping("/detail")
    @ApiOperation("投资订单的详情展示-易简")
    public Result<InvestOrderStatusDetailResponseVO> orderDetail(@RequestBody @Valid InvestOrderDetailRequestVO investOrderDetailRequestVO) {
        logger.info("orderDetail investOrderDetailRequestVO:{}", JSON.toJSON(investOrderDetailRequestVO));
        InvestStatusResponseDTO responseDTO = investOrderDubboService.queryInvestOrderDetail(investOrderDetailRequestVO.getOrderId());
        InvestOrderStatusDetailResponseVO responseVO = new InvestOrderStatusDetailResponseVO();
        if (responseDTO != null) {
            responseVO.setOrderId(responseDTO.getOrderId());
            responseVO.setProjectId(responseDTO.getProjectId());
            responseVO.setInvestType(responseDTO.getInvestType());
            responseVO.setAmount(responseDTO.getAmount());
            responseVO.setHeadImg(responseDTO.getHeadImg());
            responseVO.setNickName(responseDTO.getNickName());
            responseVO.setProductType(responseDTO.getProductType());
            responseVO.setProductTypeDesc(responseDTO.getProductTypeDesc());
            responseVO.setBorrowRate(responseDTO.getBorrowRate());
            responseVO.setDeadline(responseDTO.getDeadline());
            responseVO.setDeadlineUnit(responseDTO.getDeadlineUnit());
            responseVO.setAddRate(responseDTO.getAddRate());
            responseVO.setStatus(responseDTO.getStatus());
            responseVO.setRepaymentType(responseDTO.getRepaymentType());
            responseVO.setPrize(responseDTO.getPrize());
            responseVO.setSubmitTime(responseDTO.getSubmitTime());
            responseVO.setCalInterTime(responseDTO.getCalInterTime());
            responseVO.setContractAmount(responseDTO.getContractAmount());
            responseVO.setCurrentPeriod(responseDTO.getCurrentPeriod());
            responseVO.setCurrentRepayAmount(responseDTO.getCurrentRepayAmount());
            responseVO.setCurrentTotalAmount(responseDTO.getCurrentTotalAmount());
            responseVO.setEndTime(responseDTO.getEndTime());
            responseVO.setExpireTime(responseDTO.getExpireTime());
            responseVO.setFullScaleAmount(responseDTO.getFullScaleAmount());
            responseVO.setOrderCloseTime(responseDTO.getOrderCloseTime());
            responseVO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter());
            responseVO.setTotalRepayPeriods(responseDTO.getTotalRepayPeriods());
            responseVO.setRepayTime(responseDTO.getRepayTime());
            responseVO.setRepayAmount(responseDTO.getRepayAmount());
            responseVO.setRemainRecuitTime(responseDTO.getRemainRecuitTime());
            responseVO.setMessage(responseDTO.getMessage());
            responseVO.setTransferAmount(responseDTO.getTransferAmount());
            responseVO.setRicevutoAmount(responseDTO.getRicevutoAmount());
            responseVO.setCreditorSaleDetailId(responseDTO.getCreditorSaleDetailId());
            responseVO.setCreditorSaleUserId(responseDTO.getCreditorSaleUserId());
            responseVO.setRemainingDeadlineMonth(responseDTO.getRemainingDeadlineMonth());
            responseVO.setRemainingDeadlineDay(responseDTO.getRemainingDeadlineDay());
            responseVO.setIsEnterpriseProject(responseDTO.getIsEnterpriseProject());
            responseVO.setIsShowProjectGroup(responseDTO.getIsShowProjectGroup());
            responseVO.setIsShowOtherLoanTypeLabel(responseDTO.getIsShowOtherLoanTypeLabel());
            responseVO.setCreditorPrincipal(responseDTO.getCreditorPrincipal());
            responseVO.setAssigneeInterest(responseDTO.getAssigneeInterest());
            responseVO.setDiscountAmount(responseDTO.getDiscountAmount());

            responseVO.setReferenceIncome(responseDTO.getReferenceIncome());
            responseVO.setInterest(responseDTO.getInterest());
            responseVO.setPenaltyFee(responseDTO.getPenaltyFee());
            responseVO.setPlatformAddInterest(responseDTO.getPlatformAddInterest());
            responseVO.setPrizeAddInterest(responseDTO.getPrizeAddInterest());
        }
        String debtOnOff = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.DEBT_ON_OFF);
        String debtLaunchOnOff = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.DEBT_LAUNCH_ON_OFF);
        responseVO.setDebtOnOff(StringUtils.equals("1", debtOnOff) && StringUtils.equals("1", debtLaunchOnOff) ? "1" : "0");

        logger.info("orderDetail responseVO:{}", JSON.toJSON(responseVO));
        return Result.with(responseVO);
    }

    @PostMapping("/getProtocollo")
    @ApiOperation("相关协议-易简")
    public Result<List<ProtocolloResponseVO>> getProtocollo(@RequestBody @Valid InvestOrderDetailRequestVO investOrderDetailRequestVO) {
        String userId = PrincipalContext.getUserId();
        logger.info("getProtocollo userId：{}, investOrderDetailRequestVO:{}", userId, JSON.toJSON(investOrderDetailRequestVO));

        List<ProtocolloResponseVO> responseVOS = new ArrayList<>();
        if(Byte.valueOf("1").equals(investOrderDetailRequestVO.getType())){
            InvestProtocolloResponseDTO responseDTO = investOrderDubboService.queryInvestProtocollo(investOrderDetailRequestVO.getOrderId(), userId);
            //居间借款合同
            ProtocolloResponseVO loanResponseVO = new ProtocolloResponseVO();
            loanResponseVO.setName(ProtocolloUrlEnum.LOAN_CONTRACT.getName());
            responseVOS.add(loanResponseVO);
            String loanUrl = responseDTO.getLoanContractUrl();
            if (Objects.isNull(loanUrl)) {
                loanUrl = getContractUrl(responseDTO);
                loanUrl = loanUrl + String.format(ProtocolloUrlEnum.LOAN_CONTRACT.getParam(), responseDTO.getBorrowerUserId(), responseDTO.getProjectId());
            }
            loanResponseVO.setUrl(loanUrl);
            UserIdentityInfoResponseDTO identityInfoResponseDTO = userIdentityDubboService.get(PrincipalContext.getUserId());
            //普通投资人
            if (Byte.valueOf("1").equals(responseDTO.getUserRole())) {
                generateRiskContractUrl(responseDTO, responseVOS, identityInfoResponseDTO.getName());
                //债权出让人
            } else if (Byte.valueOf("2").equals(responseDTO.getUserRole())) {
                generateRiskContractUrl(responseDTO, responseVOS, identityInfoResponseDTO.getName());
                ProtocolloResponseVO creditorAgreementByTransferor = new ProtocolloResponseVO();
                creditorAgreementByTransferor.setName(ProtocolloUrlEnum.CREDITOR_AGREEMENT_BY_TRANSFEROR.getName());
                creditorAgreementByTransferor.setUrl(responseDTO.getCreditorAgreementUrl());
                responseVOS.add(creditorAgreementByTransferor);
                generateCreditorRiskAgreement(responseDTO, responseVOS);
                //债权受让人
            } else if (Byte.valueOf("3").equals(responseDTO.getUserRole())) {
                ProtocolloResponseVO creditorAgreementByTransferor = new ProtocolloResponseVO();
                creditorAgreementByTransferor.setName(ProtocolloUrlEnum.CREDITOR_AGREEMENT_BY_ASSIGNEE.getName());
                creditorAgreementByTransferor.setUrl(responseDTO.getCreditorAgreementUrl());
                responseVOS.add(creditorAgreementByTransferor);
                generateCreditorRiskAgreement(responseDTO, responseVOS);
            }

        }else {
            IntelligenceProtocolloRequestDTO requestDTO = new IntelligenceProtocolloRequestDTO();
            requestDTO.setUserId(userId);
            requestDTO.setPackageInvestOrderId(investOrderDetailRequestVO.getOrderId());
            InvestProtocolloResponseDTO responseDTO = investOrderDubboService.queryIntelligenceInvestProtocollo(requestDTO);

            ProtocolloResponseVO IntelligentContract = new ProtocolloResponseVO();
            IntelligentContract.setName("智能投服务协议");
            IntelligentContract.setUrl(responseDTO.getIntelligentContractUrl());
            responseVOS.add(IntelligentContract);

            ProtocolloResponseVO IntelligenceRisk = new ProtocolloResponseVO();
            IntelligenceRisk.setName("风险提示书");
            IntelligenceRisk.setUrl(responseDTO.getIntelligenceRiskContractUrl());
            responseVOS.add(IntelligenceRisk);
        }
        return Result.with(responseVOS);
    }

    /**
     * 债权转让服务风险书
     *
     * @param responseDTO
     * @param responseVOS
     */
    private void generateCreditorRiskAgreement(InvestProtocolloResponseDTO responseDTO, List<ProtocolloResponseVO> responseVOS) {
        ProtocolloResponseVO creditorAgreementByTransferor = new ProtocolloResponseVO();
        creditorAgreementByTransferor.setName(ProtocolloUrlEnum.CREDITOR_AGREEMENT_RISK_AGREEMENT.getName());
        creditorAgreementByTransferor.setUrl(responseDTO.getCreditorRiskAgreementUrl());
        responseVOS.add(creditorAgreementByTransferor);

    }

    /**
     * 风险提示书
     *
     * @param responseDTO
     * @param responseVOS
     * @param name
     */
    private void generateRiskContractUrl(InvestProtocolloResponseDTO responseDTO, List<ProtocolloResponseVO> responseVOS, String name) {
        ProtocolloResponseVO responseVO = new ProtocolloResponseVO();
        String riskContract = responseDTO.getRiskAgreementUrl();
        if (Objects.isNull(riskContract)) {
            try {
                riskContract = h5InvestRiskTipsUrl + ProtocolloUrlEnum.RISK_AGREEMENT.getParam();
                riskContract = riskContract + URLEncoder.encode(name, "utf-8");
            } catch (UnsupportedEncodingException e) {
                log.error("风险提示书，用户名编码失败name:{}", name);
            }
        }
        responseVO.setName(ProtocolloUrlEnum.RISK_AGREEMENT.getName());
        responseVO.setUrl(riskContract);
        responseVOS.add(responseVO);
    }

    /**
     * 选取合同
     *
     * @param responseDTO
     * @return
     */
    private String getContractUrl(InvestProtocolloResponseDTO responseDTO) {
        //极速借
        String url = this.h5FastloanContractUrl;
        //土巴兔
        if (ProjectTypeEnum.DECORATION_LOAN.getValue().equals(responseDTO.getType())) {
            url = this.h5orgloanContractUrl;
            //鸿特
        } else if (ProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(responseDTO.getType())) {
            if (OrgConstant.JUNTUO_ORG_ID.equals(responseDTO.getOrgId()) && PeriodUnitEnum.DAY.getValue().equals(responseDTO.getDeadlineUnit())) {
                if (BorrowerTypeEnum.COMPANY.getType().equals(responseDTO.getBorrowerType())) {
                    url = this.h5JunTuoCompanyFastLoanContract;  //企业
                } else {
                    url = this.h5JunTuoPersonalFastLoanContract;  //个人
                }
            } else {
                if (BorrowerTypeEnum.COMPANY.getType().equals(responseDTO.getBorrowerType())) {
                    url = this.h5OrgCompanyFastLoanContract;   //企业
                } else {
                    url = this.h5OrgPersonalFastLoanContract;  //个人
                }
            }
        }
        return url;
    }

    @PostMapping("/receivePaymentPlan/list")
    @ApiOperation("投资订单-回款计划列表-黄敏")
    public Result<List<InvestOrderReceivePaymentPlanResponseVO>> receivePaymentPlanList(@RequestBody @Valid InvestOrderIdRequestVO requestVO) {
        logger.info("receivePaymentPlanList requestVO:{}", JSON.toJSON(requestVO));
        List<InvestOrderReceivePaymentPlanResponseVO> responseVOList = new ArrayList<>();
        List<InvestOrderReceivePaymentPlanDTO> planDTOList = receivePaymentPlanDubboService.receivePaymentPlanList(requestVO.getInvestOrderId());

        planDTOList.forEach(p -> {
            InvestOrderReceivePaymentPlanResponseVO responseVO = new InvestOrderReceivePaymentPlanResponseVO();
            responseVO.setInvestOrderId(p.getInvestOrderId());
            responseVO.setPlanId(p.getPlanId());
            responseVO.setPeriodNum(p.getPeriodNum());
            responseVO.setReceiveDate(p.getReceiveDate());
            responseVO.setReturnStatus(p.getReturnStatus());
            responseVO.setReceiveDisplayStatus(p.getReceiveDisplayStatus());
            responseVO.setDueAmount(p.getDueAmount());
            responseVO.setReceivedAmount(p.getReceivedAmount());
            responseVO.setNumberOfTransfers(p.getNumberOfTransfers());
            responseVO.setClearingPeriodNumber(p.getClearingPeriodNumber());
            responseVO.setCurrentTime(new Date());
            responseVOList.add(responseVO);
        });
        logger.info("receivePaymentPlanList requestVO:{}", JSON.toJSON(responseVOList));
        return Result.with(responseVOList);
    }

    @PostMapping("/receivePaymentPlan/detail")
    @ApiOperation("投资订单-某期回款计划详情-黄敏")
    public Result<InvestOrderReceivePaymentDetailResponseVO> receivePaymentPlanDetail(@RequestBody @Valid InvestOrderReceivePaymentPlanDetailRequestVO requestVO) {
        logger.info("receivePaymentPlanDetail requestVO{}", JSON.toJSON(requestVO));
        InvestOrderReceivePaymentDetailResponseVO responseVO = new InvestOrderReceivePaymentDetailResponseVO();
        InvestOrderReceivePaymentDetailDTO detailDTO = receivePaymentPlanDubboService.receivePaymentPlanDetail(requestVO.getInvestOrderId(), requestVO.getPlanId());

        // 待收明细
        InvestOrderReceivePaymentDetailResponseVO.AmountDetail dueDetailResponse = new InvestOrderReceivePaymentDetailResponseVO.AmountDetail();
        InvestOrderReceivePaymentDetailDTO.AmountDetail dueDetail = detailDTO.getDueDetail();
        dueDetailResponse.setCapital(dueDetail.getCapital());
        dueDetailResponse.setInterest(dueDetail.getInterest());
        dueDetailResponse.setAddInterest(dueDetail.getAddInterest());
        dueDetailResponse.setPenaltyFee(dueDetail.getPenaltyFee());

        // 已收明细
        InvestOrderReceivePaymentDetailResponseVO.AmountDetail receivedDetailResponse = new InvestOrderReceivePaymentDetailResponseVO.AmountDetail();
        InvestOrderReceivePaymentDetailDTO.AmountDetail receivedDetail = detailDTO.getReceivedDetail();
        receivedDetailResponse.setCapital(receivedDetail.getCapital());
        receivedDetailResponse.setInterest(receivedDetail.getInterest());
        receivedDetailResponse.setPenaltyFee(receivedDetail.getPenaltyFee());
        receivedDetailResponse.setAddInterest(receivedDetail.getAddInterest());

        responseVO.setInvestOrderId(detailDTO.getInvestOrderId())
                .setPeriodNum(detailDTO.getPeriodNum())
                .setExpectReceiveDate(detailDTO.getExpectReceiveDate())
                .setActualReceiveDate(detailDTO.getActualReceiveDate())
                .setPenaltyFeeBeginDate(detailDTO.getPenaltyFeeBeginDate())
                .setPenaltyFeeEndDate(detailDTO.getPenaltyFeeEndDate())
                .setTotalAmount(detailDTO.getTotalAmount())
                .setDueDetail(dueDetailResponse)
                .setReceivedDetail(receivedDetailResponse)
                .setInterestBeginDate(detailDTO.getInterestBeginDate())
                .setInterestEndDate(detailDTO.getInterestEndDate())
                .setAdvanceHints(detailDTO.getAdvanceHints())
                .setOverdueDays(detailDTO.getOverdueDays())
                .setReceivedStatus(detailDTO.getReceivedStatus())
                .setClearingPeriodNumber(detailDTO.getClearingPeriodNumber())
                .setNumberOfTransfers(detailDTO.getNumberOfTransfers());
        logger.info("receivePaymentPlanDetail responseVO{}", JSON.toJSON(responseVO));
        return Result.with(responseVO);
    }

    @PostMapping("/investOrderList")
    @ApiOperation("PC投资订单列表-黄敏")
    public Result<PageResponseVO<InvestOrderListResponseVO>> investOrderList(@RequestBody @Valid InvestOrderListRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        logger.info("investOrderList userId={}, requestVO:{}", userId, JSON.toJSON(requestVO));

        InvestOrderListRequestDTO requestDTO = new InvestOrderListRequestDTO();
        requestDTO.setUserId(userId);
        requestDTO.setType(requestVO.getType());
        requestDTO.setStatus(requestVO.getStatus());
        requestDTO.setPageSize(requestVO.getPageSize());
        requestDTO.setPageNumber(requestVO.getPageNumber());
        PageResponseDTO<InvestOrderListResponseDTO> pageResponseDTO = receivePaymentPlanDubboService.investOrderList(requestDTO);

        List<InvestOrderListResponseVO> list = new LinkedList<>();
        InvestOrderListResponseVO responseVO = new InvestOrderListResponseVO();
        PageResponseVO<InvestOrderListResponseVO> pageResponseVO = new PageResponseVO<>();
        if (pageResponseDTO == null) {
            return Result.with(pageResponseVO);
        }

        pageResponseVO.setTotalPage(pageResponseDTO.getTotalPage());
        pageResponseVO.setTotalCount(pageResponseDTO.getTotalCount());
        if (pageResponseDTO.getItems().size() > 0) {
            for (InvestOrderListResponseDTO responseDTO : pageResponseDTO.getItems()) {
                responseVO.setAllNum(responseDTO.getAllNum());
                responseVO.setNormalReceivingNum(responseDTO.getNormalReceivingNum());
                responseVO.setOverdueNum(responseDTO.getOverdueNum());
                responseVO.setCollectingNum(responseDTO.getCollectingNum());
                responseVO.setClearingNum(responseDTO.getClearingNum());
                responseVO.setCloseNum(responseDTO.getCloseNum());
                if (responseDTO.getList() != null && responseDTO.getList().size() > 0) {
                    List<InvestOrderListResponseVO.InvestOrderList> investOrderList = new ArrayList<>();
                    responseDTO.getList().forEach(i -> {
                        InvestOrderListResponseVO.InvestOrderList investOrder = new InvestOrderListResponseVO.InvestOrderList();
                        investOrder.setOrderId(i.getOrderId());
                        investOrder.setProjectId(i.getProjectId());
                        investOrder.setContractAmount(i.getContractAmount());
                        investOrder.setBorrowRate(i.getBorrowRate());
                        investOrder.setDeadline(i.getDeadline());
                        investOrder.setDeadlineUnit(i.getDeadlineUnit());
                        investOrder.setInvestDate(i.getInvestDate());
                        investOrder.setProjectStatus(i.getProjectStatus());
                        investOrder.setToViewContractUrl(i.getToViewContractUrl());
                        investOrder.setDownloadContractUrl(i.getDownloadContractUrl());
                        investOrderList.add(investOrder);
                    });
                    responseVO.setList(investOrderList);
                }
                list.add(responseVO);
            }
            pageResponseVO.setItems(list);
        }
        return Result.with(pageResponseVO);
    }

    @PostMapping("/receivableDetail")
    @ApiOperation("PC我的投资页-回款详情-黄敏")
    public Result<ReceivableDetailResponseVO> receivableDetail(@RequestBody @Valid InvestOrderIdRequestVO requestVO) {
        logger.info("receivableDetail requestVO:{}", JSON.toJSON(requestVO));
        ReceivableDetailResponseDTO responseDTO = receivePaymentPlanDubboService.receivableDetail(requestVO.getInvestOrderId());
        ReceivableDetailResponseVO responseVO = new ReceivableDetailResponseVO();
        responseVO.setInvestOrderId(responseDTO.getInvestOrderId());
        responseVO.setProjectId(responseDTO.getProjectId());
        responseVO.setTitle(responseDTO.getTitle());
        responseVO.setBorrowRate(responseDTO.getBorrowRate());
        responseVO.setRepaymentType(responseDTO.getRepaymentType());
        responseVO.setDeadline(responseDTO.getDeadline());
        responseVO.setDeadlineUnit(responseDTO.getDeadlineUnit());
        List<ReceivableDetailResponseVO.ReceivableList> receivableList = new ArrayList<>();
        responseDTO.getList().forEach(list -> {
            ReceivableDetailResponseVO.ReceivableList receivable = new ReceivableDetailResponseVO.ReceivableList();
            receivable.setCapital(list.getCapital());
            receivable.setInterest(list.getInterest());
            receivable.setReward(list.getReward());
            receivable.setCurrentPeriod(list.getCurrentPeriod());
            receivable.setReceiveDate(list.getReceiveDate());
            receivable.setReceivedStatus(list.getReceivedStatus());
            receivableList.add(receivable);
        });
        responseVO.setList(receivableList);
        return Result.with(responseVO);
    }

    @PostMapping("/receivableCalendar")
    @ApiOperation("PC账户首页-回款日历-黄敏")
    public Result<List<ReceivableCalendarResponseVO>> receivableCalendar(@RequestBody @Valid ReceivableCalendarRequestVO requestVO) {
        String userId = String.valueOf(PrincipalContext.getUserId());
        logger.info("receivableCalendar userId={}, requestVO:{}", userId, JSON.toJSON(requestVO));
        MyloanRequestDTO dto = new MyloanRequestDTO();
        dto.setUserId(userId);
        dto.setPageSize(Integer.MAX_VALUE);

        // 获取当月第一天和最后一天
        Calendar cale = Calendar.getInstance();
        cale.setTime(requestVO.getQueryDate());

        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        dto.setStartTime(cale.getTime());

        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        dto.setEndTime(cale.getTime());

        List<BackToArticleDetails> detailsList = receivePaymentPlanDubboService.receivableCalendar(dto);
        List<ReceivableCalendarResponseVO> responseVOList = new ArrayList<>();
        detailsList.forEach(d -> {
            ReceivableCalendarResponseVO responseVO = new ReceivableCalendarResponseVO();
            responseVO.setReceivedDate(d.getReceivedDate());
            responseVO.setExpectReceivableAmount(d.getExpectReceivableAmount());
            responseVOList.add(responseVO);
        });
        logger.info("receivableCalendar userId={}, responseVOList:{}", userId, JSON.toJSON(responseVOList));
        return Result.with(responseVOList);
    }

    @PostMapping("/getRepaymentPlan")
    @ApiOperation("回款计划-易简")
    public Result<PageResponseVO<ProjectDetailsRepaymentResponseVO>> getRepaymentPlan(@RequestBody @Valid ProjectIdRequestVO requestVO) {
        ProjectBorrowerPlanRequestDTO requestDTO = new ProjectBorrowerPlanRequestDTO();
        requestDTO.setProjectId(requestVO.getProjectId());
        requestDTO.setPageNumber(requestVO.getPageNumber());
        requestDTO.setPageSize(requestVO.getPageSize());
        PageResponseDTO<ProjectBorrowerPlanResponseDTO> planPageDTO = investOrderDubboService.getPlanByProjectId(requestDTO);

        PageResponseVO<ProjectDetailsRepaymentResponseVO> pageResponseVO = new PageResponseVO<>();
        List<ProjectDetailsRepaymentResponseVO> responseVOList = new ArrayList<ProjectDetailsRepaymentResponseVO>();

        if (planPageDTO.getTotalCount() > 0) {
            for (ProjectBorrowerPlanResponseDTO p : planPageDTO.getItems()) {
                ProjectDetailsRepaymentResponseVO responseVO = new ProjectDetailsRepaymentResponseVO();
                responseVO.setCurrentPeriod(p.getCurrentPeriod());
                responseVO.setCapital(p.getCapital());
                responseVO.setInterest(p.getInterest());
                responseVO.setReceivedStatus(p.getRefundStatus());
                responseVO.setRepaymentAmount(p.getRepaymentAmount());
                responseVO.setRepaymentDate(p.getRefundDate());
                responseVOList.add(responseVO);
            }
        }

        pageResponseVO.setItems(responseVOList);
        pageResponseVO.setTotalCount(planPageDTO.getTotalCount());
        pageResponseVO.setTotalPage(planPageDTO.getTotalPage());

        return Result.with(pageResponseVO);
    }

    @AuthIgnore
    @PostMapping("/queryPCProjectInfoDetail")
    @ApiOperation("标的详情查询")
    public Result<QueryPCProjectInfoResponseVO> queryPCProjectInfoDetail(@RequestBody @Valid ProjectBorrowDetailRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        MyProjectRequestDTO dto = new MyProjectRequestDTO();
        dto.setUserId(userId);
        dto.setProjectId(requestVO.getProjectId());
        UserProjectStatisticResponseDTO userProjectStatisticResponseDTO = myLoanDubboService.queryProjectInfoDetail(dto);
        QueryPCProjectInfoResponseVO responseVO = JSON.parseObject(JSON.toJSONString(userProjectStatisticResponseDTO), QueryPCProjectInfoResponseVO.class);
        responseVO.setInvestBeginAmount(new BigDecimal(100));
        responseVO.setIncreaseAmount(new BigDecimal(100));
        responseVO.setGuaranteeWay("第三方担保公司担保");
        responseVO.setInvestorCondition("风险承受能力\"保守型\"及以上");
        return Result.with(responseVO);
    }

    @PostMapping("/555/myInvestAmountStatistics")
    @ApiOperation("我的投资金额统计-黄敏")
    public Result<InvestAmountStatisticsResponseVO> myInvestAmountStatistics(@RequestBody @Valid InvestAmountStatisticsRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        logger.info("myInvestAmountStatistics userId={}, requestVO:{}", userId, JSON.toJSON(requestVO));

        InvestAmountStatisticsRequestDTO requestDTO = new InvestAmountStatisticsRequestDTO();
        requestDTO.setUserId(userId);
        requestDTO.setQueryType(requestVO.getQueryType());
        Future<InvestAmountStatisticsResponseDTO> dueInFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.myInvestAmountStatistics(requestDTO));

        Future<List<StatisticUserBillAmountReponseDTO>> receivedStatisticFuture = null;

        Future<BigDecimal> todayReturnMoneyFuture = null;

        Future<InvestAmountStatisticsResponseDTO> intelligenceDueInFuture = null;
        Future<InvestAmountStatisticsResponseDTO> creditDueInFuture = null;
        Future<InvestAmountStatisticsResponseDTO> mortgageDueInFuture = null;
        Future<InvestAmountStatisticsResponseDTO> transferDueInFuture = null;

        // 查询全部
        if(Byte.valueOf("0").equals(requestVO.getQueryType())) {
            StatisticUserBillAmountRequestDTO statisticUserBillAmountRequestDTO = new StatisticUserBillAmountRequestDTO();
            List<BillAmountStatisticsEnum> billAmountStatisticsEnums = Arrays.asList(BillAmountStatisticsEnum.ACCEPTED_INTEREST,
                    BillAmountStatisticsEnum.PENALTY_INTEREST,
                    BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST,
                    BillAmountStatisticsEnum.CARD_AND_REDPACKET_INVEST,
                    BillAmountStatisticsEnum.CARD_INCREASE_INTEREST,
                    BillAmountStatisticsEnum.INVEST_CASHBACK);
            statisticUserBillAmountRequestDTO.setUserId(userId);
            statisticUserBillAmountRequestDTO.setBillAmountStatisticsEnums(billAmountStatisticsEnums);

            receivedStatisticFuture = RpcContext.getContext().asyncCall(() -> userBillStatisticsDubboService.statisticUserBillAmounts(statisticUserBillAmountRequestDTO));


            todayReturnMoneyFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.getTodayReturnMoney(requestDTO));


            requestDTO.setQueryType(Byte.valueOf("1"));
            intelligenceDueInFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.myInvestAmountStatistics(requestDTO));
            requestDTO.setQueryType(Byte.valueOf("2"));
            creditDueInFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.myInvestAmountStatistics(requestDTO));
            requestDTO.setQueryType(Byte.valueOf("3"));
            mortgageDueInFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.myInvestAmountStatistics(requestDTO));
            requestDTO.setQueryType(Byte.valueOf("4"));
            transferDueInFuture = RpcContext.getContext().asyncCall(() -> investOrderDubboService.myInvestAmountStatistics(requestDTO));
        }

        InvestAmountStatisticsResponseVO responseVO = new InvestAmountStatisticsResponseVO();
        try {
            InvestAmountStatisticsResponseDTO dueIn = dueInFuture.get();
            responseVO.setDueInCorpusInterest(dueIn.getDueInCorpusInterest());
            responseVO.setDueInCorpus(dueIn.getDueInCorpus());
            responseVO.setReferenceInterest(dueIn.getReferenceInterest());
        } catch (Exception e) {
            log.error("远程调用服务失败InterruptedException:", e);
        }

        if(Byte.valueOf("0").equals(requestVO.getQueryType())){
            try {
                // 今日待回款金额
                BigDecimal todayReturnMoney = todayReturnMoneyFuture.get();
                responseVO.setTodayReturnMoney(todayReturnMoney);

                List<StatisticUserBillAmountReponseDTO> receivedStatistic = receivedStatisticFuture.get();
                logger.info("myInvestAmountStatistics statisticUserBillAmounts userId:{}, receivedStatistic:{}", userId, JSON.toJSON(receivedStatistic));
                BigDecimal earnedIncome = BigDecimal.ZERO;
                for (StatisticUserBillAmountReponseDTO statisticUserBillAmountReponseDTO: receivedStatistic) {
                    if(statisticUserBillAmountReponseDTO != null) {
                        if(BillAmountStatisticsEnum.ACCEPTED_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
                            responseVO.setReceivedInterest( statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount());
                            earnedIncome = earnedIncome.add(responseVO.getReceivedInterest());
                        }
                        if(BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
                            responseVO.setPlatformAddInterest( statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount());
                            earnedIncome = earnedIncome.add(responseVO.getPlatformAddInterest());
                        }
                        if(BillAmountStatisticsEnum.PENALTY_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
                            responseVO.setReceivedPenaltyFee( statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount());
                            earnedIncome = earnedIncome.add(responseVO.getReceivedPenaltyFee());
                        }
                        if(BillAmountStatisticsEnum.CARD_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
                            responseVO.setRaiseInterestRateCoupons( statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount());
                            earnedIncome = earnedIncome.add(responseVO.getRaiseInterestRateCoupons());
                        }
                        if(BillAmountStatisticsEnum.INVEST_CASHBACK.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
                            responseVO.setInvestmentCashback( statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount());
                            earnedIncome = earnedIncome.add(responseVO.getInvestmentCashback());
                        }
                    }
                }

                responseVO.setEarnedIncome(earnedIncome);

                InvestAmountStatisticsResponseDTO intelligenceDueIn = intelligenceDueInFuture.get();
                logger.info("myInvestAmountStatistics userId={}, intelligenceDueIn:{}", userId, JSON.toJSON(intelligenceDueIn));
                responseVO.setIntelligenceDueInAmount(intelligenceDueIn.getDueInCorpusInterest());

                InvestAmountStatisticsResponseDTO creditDueIn = creditDueInFuture.get();
                logger.info("myInvestAmountStatistics userId={}, creditDueIn:{}", userId, JSON.toJSON(creditDueIn));
                responseVO.setCreditDueInAmount(creditDueIn.getDueInCorpusInterest());

                InvestAmountStatisticsResponseDTO mortgageDueIn = mortgageDueInFuture.get();
                logger.info("myInvestAmountStatistics userId={}, mortgageDueIn:{}", userId, JSON.toJSON(mortgageDueIn));
                responseVO.setMortgageDueInAmount(mortgageDueIn.getDueInCorpusInterest());

                InvestAmountStatisticsResponseDTO transferDueIn = transferDueInFuture.get();
                logger.info("myInvestAmountStatistics userId={}, transferDueIn:{}", userId, JSON.toJSON(transferDueIn));
                responseVO.setTransferDueInAmount(transferDueIn.getDueInCorpusInterest());

            } catch (Exception e) {
                log.error("远程调用服务失败InterruptedException:", e);
            }

            // 检查用户是否有信用借或机构标的投资记录
            UserHasInvestResponseDTO userHasInvestResponseDTO = investOrderDubboService.checkUserHasInvest(userId);
            responseVO.setHasOrgInvest(userHasInvestResponseDTO.isHasOrgInvest());
            responseVO.setHasCreditLoanInvest(userHasInvestResponseDTO.isHasCreditLoanInvest());
        }

        // 债转开关
        CreditorConfigDTO notifyDTO = creditorConfigDubboService.getCreditorConfigs();
        if (notifyDTO != null) {
            responseVO.setCreditorSwitch(notifyDTO.getCreditorSwitch());
        }

        // 智能投开关
        IntelligenceInvestSwitchResponseDTO switchResponseDTO = intelligenceInvestDubboService.intelligenceInvestSwitch(Byte.valueOf("0"));
        if (switchResponseDTO != null) {
            responseVO.setIntelligenceSwitch(switchResponseDTO.getIntelligenceInvestSwitch().intValue());
        }

        return Result.with(responseVO);
    }

}
